Completed
Push — master ( ef468c...cf2011 )
by Mark
15s queued 12s
created

Collection.where   A

Complexity

Conditions 5

Size

Total Lines 11
Code Lines 10

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 5
eloc 10
dl 0
loc 11
rs 9.3333
c 0
b 0
f 0
1
import * as Operators from './Collection/Where/Operators';
2
3
/**
4
 *
5
 */
6
export default class Collection extends Array {
7
8
    constructor(...items) {
9
        super(...items);
10
    }
11
12
    get operators() {
13
        return {
14
            '==': Operators.equal,
15
            '!=': Operators.notEqual,
16
            '>=': Operators.gtAndEqual,
17
            '<=': Operators.ltAndEqual,
18
            '>': Operators.gt,
19
            '<': Operators.lt,
20
        }
21
    }
22
23
    first() {
24
        return this[0] ?? null;
25
    }
26
27
    jsonStringify(): string {
28
        return JSON.stringify(this);
29
    }
30
31
    last() {
32
        return this.slice(-1)[0] ?? null;
33
    }
34
35
    merge(array): Collection {
36
        this.push(...array);
37
        return this;
38
    }
39
40
    pluck(field: string, keyField = '') {
41
        const lookUpFields = field.split('.');
42
43
        if (keyField) {
44
            const lookUpKeyField = keyField.split('.');
45
            const result = {};
46
            for (const i in this) {
47
                result[this._getRowFieldResult(this[i], lookUpKeyField)] = this._getRowFieldResult(this[i], lookUpFields);
48
            }
49
            return result;
50
        }
51
52
        const result = [];
53
        for (const i in this) {
54
            result.push(this._getRowFieldResult(this[i], lookUpFields));
55
        }
56
57
        return result;
58
    }
59
60
    random() {
61
        return this[Math.round(((this.length - 1) * Math.random()))];
62
    }
63
64
    unique(field: string): Collection {
65
        const unique = {};
66
        for (const i in this) {
67
            unique[this[i][field]] = this[i];
68
        }
69
70
        return new Collection(...Object.values(unique));
71
    }
72
73
    where(field: string, operator: string, value = null): Collection {
74
        value = value ?? operator;
75
        operator = (operator === value) ? '==' : operator;
76
77
        if (!Object.prototype.hasOwnProperty.call(this.operators, operator)) {
78
            throw new Error("Invalid comparison operator used");
79
        }
80
81
        return this.whereIfFunction(field, (field, object) => {
82
            return this.operators[operator](object[field], value);
83
        })
84
    }
85
86
    whereBetween(field: string, values): Collection {
87
        return this.whereIfFunction(field, (field, object) => {
88
            const fieldValue = object[field];
89
            return fieldValue >= values[0] && fieldValue <= values[1]
90
        });
91
    }
92
93
    whereIfFunction(field: string, whereIfFunction: CallableFunction): Collection {
94
        const register = new Collection();
95
        for (const i in this) {
96
            if (whereIfFunction(field, this[i])) {
97
                register.push(this[i]);
98
            }
99
        }
100
        return register;
101
    }
102
103
    whereIn(field: string, values): Collection {
104
        return this.whereIfFunction(field, (field, object) => {
105
            return values.includes(object[field]);
106
        });
107
    }
108
109
    whereInstanceOf(classInstance): Collection {
110
        return this.whereIfFunction(null, (field, object) => {
111
            return object instanceof classInstance;
112
        });
113
    }
114
115
    whereNotBetween(field: string, values): Collection {
116
        return this.whereIfFunction(field, (field, object) => {
117
            const fieldValue = object[field];
118
            return !(fieldValue >= values[0] && fieldValue <= values[1])
119
        });
120
    }
121
122
    whereNotIn(field: string, values): Collection {
123
        return this.whereIfFunction(field, (field, object) => {
124
            return !values.includes(object[field]);
125
        });
126
    }
127
128
    whereNotInstanceOf(classInstance): Collection {
129
        return this.whereIfFunction(null, (field, object) => {
130
            return !(object instanceof classInstance);
131
        });
132
    }
133
134
    whereNotNull(field: string): Collection {
135
        return this.whereIfFunction(field, (field, object) => {
136
            return object[field] !== null;
137
        });
138
    }
139
140
    whereNull(field: string): Collection {
141
        return this.whereIfFunction(field, (field, object) => {
142
            return object[field] === null;
143
        });
144
    }
145
146
    private _getRowFieldResult(row, lookUpFields) {
147
        let resultField = row[lookUpFields[0]] ?? null;
148
        for (let i = 1; i < lookUpFields.length; i++) {
149
            const currentField = lookUpFields[i];
150
151
            if (resultField === null) {
152
                break;
153
            }
154
155
            if (resultField instanceof Collection) {
156
                return resultField.pluck(lookUpFields[i]);
157
            }
158
159
            resultField = resultField[currentField] ?? null;
160
        }
161
162
        return resultField;
163
    }
164
}